package drds.plus.sql_process.abstract_syntax_tree.expression.bind_value;

import drds.plus.common.jdbc.Parameters;
import drds.plus.common.jdbc.SetParameterMethod;
import drds.plus.common.jdbc.SetParameterMethodAndArgs;
import drds.plus.common.thread_local.ThreadLocalMap;
import drds.plus.sql_process.abstract_syntax_tree.execute_plan.ExecutePlan;
import drds.plus.sql_process.abstract_syntax_tree.expression.item.Item;
import drds.plus.sql_process.sequence.SequenceManager;
import drds.plus.sql_process.type.Type;

/**
 * sequence.next value获取的实现
 */
public class SequenceValueImpl extends BindValueImpl implements SequenceValue {
    /**
     * 等于表名TableName
     */
    private Object sequenceName;
    private Long batchMaxValue = -1L;

    public SequenceValueImpl(Object sequenceName) {
        super(0);
        this.sequenceName = sequenceName;
    }

    public Object assignment(Parameters parameters) {
        Object key = null;
        if (sequenceName instanceof BindValue) {
            key = ((BindValue) sequenceName).assignment(parameters);
        } else if (sequenceName instanceof Item) {
            key = ((BindValue) sequenceName).assignment(parameters);
        } else {
            key = sequenceName;
        }

        String keyString = Type.StringType.convert(key);
        if (parameters != null && parameters.isBatch()) {
            if (batchMaxValue < 0) {
                batchMaxValue = SequenceManager.getSequenceManager().nextValue(keyString, parameters.getBatchSize());
                ThreadLocalMap.put(ExecutePlan.LAST_SEQUENCE_VALUE, batchMaxValue);// 只记录最大的seqId
            }
            // 返回value用户做rule计算
            value = batchMaxValue - parameters.getBatchSize() + parameters.getBatchIndex() + 1;//计算出合适的值
            // 将value加入到绑定变量中
            parameters.getIndexToSetParameterMethodAndArgsMap().put(index, new SetParameterMethodAndArgs(SetParameterMethod.setLong, new Object[]{index, value}));
            return this;
        } else {
            Long nextValue = SequenceManager.getSequenceManager().nextValue(keyString);
            ThreadLocalMap.put(ExecutePlan.LAST_SEQUENCE_VALUE, nextValue);// 使用thread变量
            return nextValue;
        }
    }

    public void setOriginIndex(int index) {
        this.index = index;
    }

    public SequenceValue copy() {
        Object newName = null;
        if (sequenceName instanceof BindValue) {
            newName = ((BindValue) sequenceName).copy();
        } else if (sequenceName instanceof Item) {
            newName = ((BindValue) sequenceName).copy();
        } else {
            newName = sequenceName;
        }

        SequenceValueImpl sequenceValue = new SequenceValueImpl(newName);
        sequenceValue.setOriginIndex(index);
        return sequenceValue;
    }

    public String toString() {
        return sequenceName.toString() + ".NEXTVAL";
    }

}
